/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */
#pragma once

#include <lib3d/model/Model.h>
#include <lib3d/model/ModelInHardware.h>
#include "Model.h"
#include "Factory.h"
#include <CompilerFeatures.h>

namespace liba {
namespace lib3d {
namespace node {

class ModelSkeleton :
	public Model
{
	NODE_DEFINITION(ModelSkeleton)

	class Joint : public NodeBase
	{
		NODE_DEFINITION(Joint)

		ModelSkeleton * model;
		Joint * parent;
		Vector orientation;
		Matrix total_mat;
		Matrix initial_total_mat;
		Matrix diff_mat;
		int index;

//		void add_influence_internal(SimpleArray<float> * dst_positions, const SimpleArray<float> & src_positions);
	public:
		static const Atom node_name;

		Matrix get_joint_matrix();
		explicit Joint(ModelSkeleton * model, Joint * parent);
		Matrix start_add_influence(const Matrix & mat);
		Matrix add_influence();
		Matrix start_first_influence(const Matrix & mat);
		Matrix first_influence();
//		Matrix start_add_influence();
//		Matrix add_influence();
//		void start_first_influence();
//		void first_influence();
		int get_index()const
		{
			return index;
		}
		virtual animate::Node * FindAnimateNode( const Atom & name, bool recursion ) LIBA_OVERRIDE;
//	protected:
		virtual bool on_attribute( xml::Provider * prov, const std::string & name, const std::string & value ) LIBA_OVERRIDE;
		virtual bool on_node( xml::Provider * prov, const std::string & name ) LIBA_OVERRIDE;
	};
	class HaMod
		:	public HardwareDependentObject<hard::Manager, model::ModelInHardwareObject>
	{
	protected:
		virtual void on_add_hardware(hard::Manager::hardware_type * ha) LIBA_OVERRIDE;
	public:
		~HaMod();
		HaMod();
	};

	friend class Joint;
	typedef std::vector<Joint *> Joints;
	Joints joints;
public:
	static const Atom node_name;

	ModelSkeleton( const Atom & name, Node * parent );
	virtual ~ModelSkeleton();

	virtual void RenderToList( hard::Hardware * hardware, hard::RenderList * render_list ) LIBA_OVERRIDE;

	virtual animate::Node * FindAnimateNode( const Atom & name, bool recursion ) LIBA_OVERRIDE;
protected:
	virtual bool on_attribute( xml::Provider * prov, const std::string & name, const std::string & value ) LIBA_OVERRIDE;
	virtual bool on_node( xml::Provider * prov, const std::string & name ) LIBA_OVERRIDE;
	virtual bool on_end_node( xml::Provider * prov ) LIBA_OVERRIDE;
private:
	HaMod normal_dst;
	HaMod shadow_dst;
//	SharedPrecached<filesystem::String, model::ModelInHardware> normal_model;
//	SharedPrecached<filesystem::String, model::ModelInHardware> shadow_model;
	SharedPrecached<filesystem::String, model::Model> normal_model_src;
	SharedPrecached<filesystem::String, model::Model> shadow_model_src;
	int last_index;
	bool on_skeleton_change();
};


} // namespace node
} // namespace lib3d
} // namespace liba
using namespace liba;
